﻿/* 
  BrowserMouse 2.0 for AS3
  By Pete McBride
  
  Enables you to track the mouse position from Flash even if the mouse is 
  outside the boundaries of the SWF. Also converts Flash XY coordinates to
  Browser XY coordinates, and visa-versa, and tells you whether or not the
  mouse is currently over the SWF. Automatically factors in conditions beyond
  the normal scope of Flash, such as the SWF's position and scale on the 
  webpage.
  
  Tested with IE7, Firefox 2, Safari 2/3. Probably works on other browsers.
  Only known weakness: Sometimes shows odd values if browser is scaled. Still
  unsure how to detect browser scaling, but since so few users actually 
  use the feature, this may be okay.
  
  Technical coolness to look for: 
  
  1) Shows how to embed complex javascripts within Flash, then execute 
them using ExternalInterface.

2) Implements a few Lazy Function models to cut down on CPU usage.

3) Shows how to query the Browser for information without the need
for scripts in the Browser.
  
*/
package com.asorg.browser {
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.system.Capabilities;
	import flash.external.ExternalInterface;
	import flash.events.Event;
	import flash.utils.Timer;
	import flash.events.TimerEvent;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import com.asorg.browser.EmbedObject;


	public class BrowserInfo {


		// BrowserInfo object contains items which may affect XY values of BrowserMouse.
		static public  var _BrowserPlayerType:String;
		static public  var _BrowserName:String;
		static public  var _BrowserVersion:String;
		static public  var _isIE:Boolean;
		static public  var _userAgent:String;
		static public  var _ObjectEmbedID:String;




		public function get BrowserPlayer():String {
			return _BrowserPlayerType;
		}
		public function get IsIE():Boolean {
			return _isIE;
		}
		public function get BrowserVersion():String {
			return _BrowserVersion;
		}
		public function get BrowserName():String {
			return _BrowserName;
		}

		public function get BrowserAgent():String {
			return _userAgent;
		}

		public function get ObjectEmbedID():String {
			return _ObjectEmbedID;
		}

		// Number of previous sites the user visited prior to coming to this flash site.
		// Useful? Who knows!
		public var _NumPreviousSites:Number;

		// Offset of the Stage within the visible Flash window, in Flash coordinates, from
		// the SWF origin point (0,0).
		public var _stageOffsetX = 0;
		public var _stageOffsetY = 0;
		public function get StageOffset():Point {
			return new Point(_stageOffsetX,_stageOffsetY);
		}

		// Ofset of the Flash Window on the webpage, in Browser coordinates.
		public var _browserOffsetX:Number=0;
		public var _browserOffsetY:Number=0;
		public function get BrowserOffset():Point {
			return new Point(_browserOffsetX,_browserOffsetY);
		}
		// These are set at instantiation to the size of the root SWF as set in the 
		// Document Properties dialog box (ctrl-J). If anybody knows of a way to get
		// these dynamically, please let me know!!!
		public var _preferredWidth:Number=0;
		public var _preferredHeight:Number=0;

		// These are the actual calculated W/H of the stage in the browser, and are equivalent
		// to stage.stageWidth/Height in all tests I attempted, so this is internal only.
		public var _stageWidth:Number=0;
		public var _stageHeight:Number=0;

		// The scale of the SWF's stage as it appears to the Browser; Flash may have a different 
		// concept of how it's being scaled.
		public var _stageScaleX:Number=1;
		public var _stageScaleY:Number=1;
		public function get StageScale():Object {
			return {x:_stageScaleX,y:_stageScaleY};
		}

		// The scale of the webpage within the Browser. Normally always 1:1 unless the user has
		// tweaked/resized the page. I'm trying desperately to find a way to get this value from
		// javascript, but may be impossible since all browsers manage page scaling differently.
		// If anybody knows a way, please contact me.
		public function get BrowserScale():Object {
			return {x:1,y:1};
		}

		// Returns the rectangle of the SWF Plugin, in Browser DOM coordinates, as it appears on the webpage.
		public function get BrowserPluginRect():Rectangle {
			return new Rectangle(_browserOffsetX,_browserOffsetY,_stageWidth,_stageHeight);
		}

		// Returns a rectangle representing only the visible parts of the Stage as it appears
		// in the browser window, in flash global coordinates. Anything outside this rectangle
		// will not be seen. NOT IMPLEMENTED YET.
		public function get VisibleStageRect():Rectangle {
			return new Rectangle(-1,-1,-1,-1);
		}

		// Internal reference to the Stage, based on target param; because of AS3 security, 
		// BrowserMouse must be instantiated with a movieclip from the topmost SWF.
		public var _stage;
		public function get StageTarget() {
			return _stage;
		}

		// --------------------------------------------------------------------------------------------------
		// BROWSERINFO INSTANTIATOR
		// --------------------------------------------------------------------------------------------------

		public function BrowserInfo(target:*,  myPreferredWidth:*=null, myPreferredHeight:*=null, resizes:Boolean=true, resizeCheckInterval:Number=500) {
			// BrowserMouse works by comparing Flash's MouseLoc to that of the Browser, so we
			// need to set up an internal listener, an external callback, and then dump all
			// that embedded javascript(above) into the browser.

			// Can we even do this? Throw an exception at instantiation if any of this is not possible.
			CheckInjectable();

			// set  constants:
			if (!_BrowserPlayerType) {
				_BrowserPlayerType  = Capabilities.playerType;
			}
			_BrowserName = String(GetProperty("navigator.appName"));
			_BrowserVersion = String(GetProperty("navigator.appVersion"));
			_userAgent = String(GetProperty("navigator.userAgent"));
			_isIE = (_userAgent=="")?false:(_userAgent.indexOf("MSIE")!= -1);
			_ObjectEmbedID = EmbedObject.getId();

			_stage = target.stage;
			_preferredWidth = myPreferredWidth || _stage.stageWidth;
			_preferredHeight = myPreferredHeight || _stage.stageHeight;
			_NumPreviousSites= Number(GetProperty("history.length"));

			// Get the size, location, and scale of the SWF as it appears in the browser. If this SWF can be resized
			// within the browser dynamically, set resizes=true and this test will be performed periodically on
			// the value of resizeCheckInterval milliseconds; optionally you can just call UpdateMetrics when you feel
			// like it. Note that looking for onResize events does not always work because not all display modes
			// throw the event.
			UpdateMetrics();
			if (resizes) {
				var myTimer:Timer = new Timer(resizeCheckInterval);
				myTimer.addEventListener("timer", UpdateMetrics);
				myTimer.start();
			}
			//just an experiment
			//var myTimer2:Timer = new Timer(2000, 1);
			//myTimer2.addEventListener("timer", InjectVB);
			//myTimer2.start();
			//InjectJS(0,0);

		}

		// --------------------------------------------------------------------------------------------------
		// SCRIPT INJECTION
		// The core of BrowserInfo is it's ability to inject complex JavaScript and VBScript into webpages. 
		// This is a variation on ExternalInterface.call; rather than calling an existing page function by 
		// name, we wrap entire applications (with multiple variables and functions) into a single anonymous
		// wrapper-function. Once thus encapsulated, we fire the whole darned thing through a single
		// ExternalInterface.call() method. Properly written, the scripts will load, do their thing,
		// return a result if possible, and erase themselves from memory.
		//
		// WHY USE INJECTION? Convenience, compliance, and compatibility. Many sites will allow you to
		// display a Flash SWF, but have no means for you to upload any supporting JS or VB scripts that
		// your SWF needs. Or, you may control the Flash, but must rely on others to manage the Javascripts
		// for you, and you don't want to bother with that. By keeping your external script files inside
		// Flash, you also guarantee
		//
		// Script injection originally came about as a result of something called bookmarklets, which 
		// were cool little scripts you could add to your "favorites" menu. At the time they were popular
		// (late 90s) there wasn't a lot they could do, so they were soon forgotten. AJAX style javascripts
		// changed all that, and I and a few others soon discovered that bookmarklets worked in Flash
		// through the ExternalInterface.call method.
		//
		// Google the term "Bookmarklet" for a list of premade javascripts that are already injection
		// compatible. They will give you insight into the art of injection using javascript, and with 
		// a little tweaking, you'll be able to roll your own injected functions.
		//
		// Almost anything is possible - except using document.write() and document.writeln(), because these
		// functions require that the webpage still be open and streaming, and if Flash is running, it's
		// probably already closed and being displayed (there are exceptions). If you need Flash to dynamically
		// write to the webpage, consider using DOM commands instead, such as innerHTML and appendChild.
		//
		// VBScript injection works similarly, although we need an additional step: VBScript lacks the wrapper
		// functionality of JavaScript functions, so there's no way to pass complex scripts and applications
		// in using ExternalInterface. JavaScript to the rescue: we wrap the VBS into a series of JS commands
		// and use IE's little-known execScript() function to run the VBScript. NOTE: VBScript injection
		// only works on IE, and an exception is thrown if you try to run it on any other browser.
		//
		// Additionally, there is no way to immediately get a return value from a VBScript: you must first 
		// inject the script, and then make a second call to actually get a result from it.
		//
		// --------------------------------------------------------------------------------------------------

		public function InjectJS(script, args):* {

			var myresult = ExternalInterface.call("function(){" + script + "}", args);
			return myresult;
		}
		public function InjectVB(e):* {

			try {
				if (!IsIE) {
					throw new BrowserError("BrowserInfo: VB requires Internet Explorer.");
				}
			} catch (e) {
				// if we made it past CheckInjectable() we know we are in a browser, but
				// it's not the ***correct*** browser... VB is for IE only!
				alert(e);
				return null;
			}
			var CRLF = String.fromCharCode(13)+String.fromCharCode(10);
			var vb = DetectActiveX_vb.toString();
			var vb_arr = vb.split(CRLF);
			var jsvb="function(){" + CRLF;
			jsvb += "   var temp='';" + CRLF;
			for (var i = 0; i <vb_arr.length; i++) {
				var vbTemp = vb_arr[i];//.replace("'", "\'");
				jsvb+="   temp+=('" + vbTemp + "' + String.fromCharCode(13));" + CRLF;
			}
			jsvb+= "   window.execScript(temp, 'vbscript');" + CRLF;
			jsvb+= "}";
			trace(jsvb);
			ExternalInterface.call(jsvb);
			var holyCow = ExternalInterface.call("myAdd", "no Waiting!");
			alert(holyCow);

		}
		var fuck;

		public function CheckInjectable() {
			// Makes sure we can handle script injections, and throws any of several errors if we can't.
			// For testing purposes, we'll issue these as a warning only and allow execution to continue.
			/*try*/
			{
				if (!IsBrowser) {
					//throw new Error("Browser Required for script injection");
				}
				if (!ExternalInterface.available) {
					//throw new Error("ExternalInterface disabled.");
				}
				if (!IsScriptable) {
					//throw new Error("Browser scripting not allowed.");
				}
				} ;/*catch (e) {
				 fuck=e;
				
				trace("Warn: " + e);
				throw e
				}*/
			}

			// --------------------------------------------------------------------------------------------------
			// BROWSER DIALOG FUNCTIONS
			// These functions allow complete to access alert(), confirm(), prompt(), and (in IE) MsgBox()
			// functions from within Flash. Most browsers will completely suspend Flash while these dialogs
			// are being displayed, which may or may not de desirable. Invaluable for debugging AS within
			// browsers, as they allow you to throw up error alerts, change parameters, etc, without the
			// need to create a support structure within Flash or bloat your swfs with Components.
			//---------------------------------------------------------------------------------------------------

			public function alert(txt:String):void {
				// Spawns a javascript-style alertbox. Some browsers will suspend Flash while this is up; 
				// in others Flash will continue running in the background.

				ExternalInterface.call("alert", String(txt));
			}

			public function confirm(txt:String):Boolean {
				// Spawns a javscript-style Ok/Cancel challenge. All browsers tested will completely 
				// suspend Flash while this is up; use with discretion! Returns true (OK) or false
				// (Cancel or dismiss).

				var confirmed = ExternalInterface.call("confirm", String(txt));
				return confirmed;
			}

			public function prompt(prompt_str:String, default_str:String):String {
				// Spawns a javscript-style input challenge. All browsers tested will completely 
				// suspend Flash while this is up; use with discretion!

				var answer = ExternalInterface.call("prompt", String(prompt_str), String(default_str));
				return answer;
			}

			public function MsgBox(args:*) {
			}

			// --------------------------------------------------------------------------------------------------
			// BROWSER COOKIE FUNCTIONS
			// Complete Read/Write/Delete access to Browser Cookies from Flash.
			// --------------------------------------------------------------------------------------------------
			public function GetCookie(myCookie:String) {
			}
			public function WriteCookie(myCookie:String, myData:*) {
			}
			public function DeleteCookie(myCookie:String) {
			}


			// --------------------------------------------------------------------------------------------------
			// BROWSER INFO FUNCTIONS
			// Get Browser Properties, Query Strings
			// --------------------------------------------------------------------------------------------------

			public function GetProperty(myProp:String):String {
				// Helper function to explicitly query the browser for the specified property value. 
				// Note that this can cause the browser to crash if you try to get too complex
				// of an object: keep it to strings and numbers if possible.

				var js = "function(){return " + myProp + ";}";
				try {
					var myresult = ExternalInterface.call(js);
				} catch (e) {
					myresult=false;
				}
				return myresult;
			}
			public function GetQueryString(varName_str:String=""):String {
				// If no argument is supplied, returns entire raw query string of the hosting page
				// to Flash. Optional argument varName_str allows you to specify a specific
				// variable in the string by name, and the value of that variable will be returned.
				// Given url of http://localhost:2110/Experiments/BrowserMouseRevisited.html?foobar=foo%20bar&snafu=23
				//     BrowserInfo.GetQueryString("foobar") will return "foo%20bar"
				//     BrowserInfo.GetQueryString("snafu") will return "23"
				//     BrowserInfo.GetQueryString() will return "foobar=foo%20bar&snafu=23"

				var myresult = ExternalInterface.call(GetQueryStringValue_js, varName_str);
				return myresult;
			}

			public function get IsBrowser():Boolean {
				// Returns TRUE if the shell application is a Browser, or application that uses 
				// browser-like implementation. Doesn't tell us jack about javascript or if 
				// external interface is avaialble.
				return _BrowserPlayerType == "ActiveX" || _BrowserPlayerType == "Plugin";
			}


			public var _isScriptable;
			public function get IsScriptable():Boolean {
				// Returns TRUE if the shell application is a Browser capable of JavaScript
				// and ExternalInterface has been enabled. This differs from ExternalInterface.available
				// which doesn't factor in the "Browser" and "JavaScript" bits...
				if (_isScriptable==undefined) {
					if (IsBrowser) {
						if (ExternalInterface.available) {
							var test = ExternalInterface.call("function(){return navigator.userAgent}");
							_isScriptable=(test != null );
						} else {
							_isScriptable=false;
						}
					} else {
						_isScriptable=false;
					}
				}
				return _isScriptable;
			}

			// --------------------------------------------------------------------------------------------------
			// COORDINATE SYSTEM CONVERSIONS
			// Convert Webpage XY (pixel) coordinates to Flash Global (unit) Coordinates and visa-versa.
			// Factors in scale of Flash Plugin in webpage, its location on the page, and the 
			// offset of the Stage within the Flash Plugin.
			// --------------------------------------------------------------------------------------------------

			public function FlashToBrowser(pF:Point):Point {
				// Converts Flash (global units) coordinates to Browser (screen pixel) coordinates.
				// In IE, this value is always 2px less than it should be... not sure why.
				var bx = _browserOffsetX +(_stageScaleX * (pF.x - _stageOffsetX)) + (_isIE ? 2 : 0);
				var by =  _browserOffsetY +(_stageScaleY * (pF.y - _stageOffsetY)) + (_isIE ? 2 : 0);
				return new Point(bx,by);
			}

			public function BrowserToFlash(pB:Point):Point {
				// Converts Browser (screen pixel) coordinates to Flash (global units) coordinates.
				// In IE, this value is always 2px more than it should be... not sure why.
				var fx = ( (pB.x - _browserOffsetX)/_stageScaleX)  - (_isIE ? 2 : 0);
				var fy = ( (pB.y - _browserOffsetY)/_stageScaleY)  - (_isIE ? 2 : 0);
				return new Point(fx,fy);
			}


			// --------------------------------------------------------------------------------------------------
			// UTILITIES
			// These are just a few useful utilites that take advantage of Flash/JavaScript/VB
			// interaction. They are provided as examples for your own future expansion of BrowserInfo
			// and its subclasses.
			// --------------------------------------------------------------------------------------------------

			public function JavaScriptInterpreter():void {
				// Spawns a textbox that allows you to enter any javascript command. Useful if your flash is appearing in a
				// web dialog and you can't get access to the URL-entry field.
				//ExternalInterface.call(VB_js);
			}

			// --------------------------------------------------------------------------------------------------
			// IMPLEMENTATION
			// This is the guts of BrowserInfo
			// --------------------------------------------------------------------------------------------------


			public function UpdateMetrics(e:TimerEvent=null) {
				// Periodically gets the size and scale of the SWF as it appears in the Browser. 
				// Too bad OnResize only works for NO_SCALE, or we'd use that instead to save CPU cycles.
				// If the SWF is never going to be moved or resized on the page, set resizes=false
				// on the initter for this class, and this test will only be performed once.
				UpdateStageAspectRatio();
				UpdateStageOffset();
				UpdateBrowserOffset();
			}

			public function UpdateStageAspectRatio() {
				// Get scale of SWF as it appears in the browser. In laymen's terms, what do
				// I multiply my SWF's preferred WH by, in order to fill the window, based on the
				// current scale mode?
				//
				// This can be called explicitly at your request, or placed on a timer using the resizes=true initter.
				_stageWidth = _stage.stageWidth;
				_stageHeight = _stage.stageHeight;
				_stageScaleX =_stageWidth/_preferredWidth;
				_stageScaleY =_stageHeight/_preferredHeight;

				switch (_stage.scaleMode) {

					case StageScaleMode.NO_SCALE :
						// Easiest! Locked Aspect Ratio, and no scaling at all. Stage may show some cropping
						// if the application window (plug, activex, etc) is too small.
						_stageScaleX = 1;
						_stageScaleY = 1;
						break;

					case StageScaleMode.EXACT_FIT :
						// Second easiest! Scale W and/or H, do not maintain Aspect Ratio. No cropping whatsoever!
						_stageScaleX = _stageScaleX;
						_stageScaleY = _stageScaleY;
						break;

					case StageScaleMode.NO_BORDER :
						// Locked Aspect Ratio, so both values will be equal to the _greater_ of the two.
						// This results in a "zoomed, cropped" effect where only part of the stage may be visible.
						_stageScaleX =  Math.max(_stageScaleX, _stageScaleY);
						_stageScaleY =  Math.max(_stageScaleX, _stageScaleY);
						break;

					case StageScaleMode.SHOW_ALL :
						// Locked Aspect Ratio, so both values will be equal to the _lesser_ of the two.
						// This results in a "shrunken, barred" effect, but everything is visible.
						_stageScaleX =  Math.min(_stageScaleX, _stageScaleY);
						_stageScaleY =  Math.min(_stageScaleX, _stageScaleY);
						break;
				}
			}
			public function UpdateBrowserOffset() {
				// Where the upper-left corner of the SWF is, within the webpage, in Browser coordinates.
				var js = BrowserOffset_js.toString();
				var jsFixed = js.replace(/InsertIDHere/g,BrowserInfo._ObjectEmbedID);
				var OffsetPoint:Object = ExternalInterface.call(jsFixed);
				if (OffsetPoint!=null) {
					_browserOffsetX = OffsetPoint.x;
					_browserOffsetY = OffsetPoint.y;
				} else {
					_browserOffsetX = 0;
					_browserOffsetY = 0;
				}
			}

			public function UpdateStageOffset() {
				// Tells you the global-stage coordinates of the point at the upper-left corner
				// of the flash application or browser object. This is only applicable in certain
				// situations, namely when the SWF is being displayed in an area that doesn't match
				// it preferred width and height, and when certain stage alignments and scale modes
				// are in effect.
				//
				// Results returned are Flash global stage coordinates, relative to the 
				// upper-left corner of the stage (always 0,0) as it appears within the Flash app window, 
				// so if you get a result where offset.x = -200, it means the swf's origin Point(0,0) is actually
				// going to be found 200 pixels *right* of the app window.
				//
				// Does not factor in the Flash Apps location or scale within the browser.
				//
				// This can be called explicitly at your request, or placed on a timer using the resizes=true initter.



				if (_stage.scaleMode == StageScaleMode.EXACT_FIT) {
					// Exact fit ignores all alignment considerations:
					_stageOffsetX = 0;
					_stageOffsetY = 0;
				} else {
					// Calculate alignment
					if (_stage.align.indexOf("L")>-1) {
						_stageOffsetX = 0;
					} else if (_stage.align.indexOf("R")>-1) {
						_stageOffsetX = 0 - ((_stageWidth ) - (_preferredWidth));
					} else {
						_stageOffsetX = 0 - ((_stageWidth/2 ) - (_preferredWidth/2));
					}
					if (_stage.align.indexOf("T")>-1) {
						_stageOffsetY = 0;
					} else if (_stage.align.indexOf("B")>-1) {
						_stageOffsetY = 0 - ((_stageHeight ) - (_preferredHeight));
					} else {
						_stageOffsetY = 0 - ((_stageHeight/2 ) - (_preferredHeight/2));
					}
					// NO_BORDER will ignore alignment in one dimension.
					if (_stage.scaleMode == StageScaleMode.NO_BORDER) {
						// Offset will be zero in the "fit" dimension and 
						// negative in the "cropped" dimension.
						_stageOffsetX = (_stageScaleX >= _stageScaleY) ? 0 : _stageOffsetX;
						_stageOffsetY = (_stageScaleX <= _stageScaleY) ? 0 : _stageOffsetY;
					}

				}
			}
			// --------------------------------------------------------------------------------------------------
			// JAVASCRIPTS
			// These XML files show how to store browser-executable javascripts directly within an AS3 file.
			// Because of the similarities between JS and AS, the AS interpreter will actually color-code
			// your javascripts properly, but note that your indents must be made manually with ***spaces*** as
			// the auto-format option will wipe out any auto-indenting the interpreter uses.
			// --------------------------------------------------------------------------------------------------


			/*
			
			
			// This is just a base wrapper for all xml-based javascripts, copy for your convenience:
			 public const baseJavascript_js:XML =
			<javascript>
			    <![CDATA[
			        function(){
			
			        }
			    ]]>
			</javascript>;
			*/
			public var setCookie_js:XML = 
			<javascript>
			    <![CDATA[
			        function(name, value, expires, path, domain, secure){
			            function setCookie( name, value, expires, path, domain, secure ) {
			                 var today = new Date();
			                 today.setTime( today.getTime() );
			                 if ( expires ) {
			                     expires = expires * 1000 * 60 * 60 * 24;
			                 }
			                 var expires_date = new Date( today.getTime() + (expires) );
			                 document.cookie = name+'='+escape( value ) +
			                    ( ( expires ) ? ';expires='+expires_date.toGMTString() : '' ) + //expires.toGMTString()
			                    ( ( path ) ? ';path=' + path : '' ) +
			                    ( ( domain ) ? ';domain=' + domain : '' ) +
			                    ( ( secure ) ? ';secure' : '' );
			            }
			            setCookie( name, value, expires, path, domain, secure ) ;
			        }
			    ]]>
			</javascript>;;
			public var getCookie_js:XML = 
			<javascript>
			<![CDATA[
			    function(name){ 
			        function getCookie( name ) {
			            var start = document.cookie.indexOf( name + "=" );
			            var len = start + name.length + 1;
			            if ( ( !start ) && ( name != document.cookie.substring( 0, name.length ) ) ) {
			                return null;
			            }
			            if ( start == -1 ) return null;
			            var end = document.cookie.indexOf( ';', len );
			            if ( end == -1 ) end = document.cookie.length;
			            return unescape( document.cookie.substring( len, end ) );
			        }
			        return getCookie( name );
			    }
			]]>
			</javascript>;;
			public var deleteCookie_js:XML =
			<javascript>
			<![CDATA[
			    function(name, path, domain){
			        function deleteCookie( name, path, domain ) {
			            if ( getCookie( name ) ) {
			                document.cookie=name+'='+((path)?';path='+path:'')+((domain)?';domain='+domain:'')+';expires=Thu, 01-Jan-1970 00:00:01 GMT';
			            }
			        }
			        deleteCookie( name, path, domain );
			    }
			]]>
			</javascript>;;
			// This javascript gets the query string from the webpage URL. You may specify
			// a specific key, or leave the argument blank to get the entire query string.
			public var GetQueryStringValue_js:XML = 
			<javascript>
			<![CDATA[
			    function(queryVar){ 
			    //  JAVASCRIPT: This external wrapper function encapsulates everything else so it can be sent in a single call()
			
			        function gup( queryVar ) {
			            queryVar = queryVar.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
			            var regexS = "[\\?&]"+queryVar+"=([^&#]*)";
			            var regex = new RegExp( regexS );
			            var results = regex.exec( window.location.href );
			            if ( results == null ) {
			                return "";
			            } else {
			                return results[1];
			            }
			        }
			        if(queryVar==""){
			            var hrefStr = window.location.href;
			            var qArr = hrefStr.split("?");
			            var qStr = qArr[1];
			            return qStr;
			        } else {
			            return gup(queryVar);
			        }
			    }
			]]>
			
			</javascript>;;
			public var BrowserOffset_js:XML =
			<javascript>
			<![CDATA[
			    function(){ 
			        //  JAVASCRIPT: This external wrapper function encapsulates everything else so it can be sent in a single call()
			
			        // [<OBJECT_EMBED_ID>] will be replaced by the EmbedObject ID of this SWF when the 
			        // javascript is sent to the brwoser for interpretation.
			         var thisSWF = document.getElementById("InsertIDHere");
			
			        //  JAVASCRIPT: This calculates the position of the SWF on the page, factoring in
			        // locations of all parents. Works in most browsers; returns x0:y0 
			        // in those few browsers that don't support it.
			        var findPos;
			        findPos = function(obj) {
			            var curleft = curtop = 0;
			            if (obj.offsetParent) {
			               do {
			                  curleft += obj.offsetLeft;
			                  curtop += obj.offsetTop;
			               } while (obj = obj.offsetParent);
			               return {x:curleft,y:curtop};
			            }
			            return {x:obj.offsetLeft,y:obj.offsetTop};
			        }
			        return findPos(thisSWF);
			    }
			]]>
			
			</javascript>;;
			// This javascript gets the query string from the URL that launched the player
			public var JavaScriptInterpreter_js:XML =
			<javascript>
			<![CDATA[
			function(){ 
			    function JSexe(){ 
			        if (valJS!='null' && valJS!='undefined')strJS=valJS; 
			        strJS=prompt('Input JavaScript code for eval():',strJS); 
			        if (strJS!=null && strJS!='' && strJS!='undefined'){  
			            setTimeout('valJS=\'\'+eval(strJS);JSexe()',10); 
			        } else{
			            valJS='';strJS='';
			        }
			     }
			     valJS='';
			     strJS='';
			     JSexe();
			 }
			]]>
			
			</javascript>;;

			// --------------------------------------------------------------------------------------------------
			// VBSCRIPTS
			// Okay, let's assume you're not satisfied with mere Javascript injection, and really need something
			// in VBScript, such as access to ActiveX, or that cool MsgBox function. There's no way to encapsulate
			// functions within VBScript... so do it with Javascript!
			//
			// NOTE: VBScripts only work in IE; attempting to send them to another browser will throw an exception.
			// --------------------------------------------------------------------------------------------------

			public var DetectActiveX_vb:XML =
			<vbscript>
			<![CDATA[
			 
			    Function myAdd(txt)
			        myAdd = "CoolShit!" + txt
			    End Function 
			
			    'do a one-time test for a version of VBScript that can handle this code'
			    detectableWithVB = False
			    If ScriptEngineMajorVersion >= 2 then
			      detectableWithVB = True
			    End If
			
			    'this next function will detect most plugins'
			    Function detectActiveXControl(activeXControlName)
			      on error resume next
			      detectActiveXControl = False
			      If detectableWithVB Then
			         detectActiveXControl = IsObject(CreateObject(activeXControlName))
			      End If
			    End Function
			
			    'and the following function handles QuickTime'
			    Function detectQuickTimeActiveXControl()
			      on error resume next
			      detectQuickTimeActiveXControl = False
			      If detectableWithVB Then
			        detectQuickTimeActiveXControl = False
			        hasQuickTimeChecker = false
			        Set hasQuickTimeChecker = CreateObject("QuickTimeCheckObject.QuickTimeCheck.1")
			        If IsObject(hasQuickTimeChecker) Then
			          If hasQuickTimeChecker.IsQuickTimeAvailable(0) Then 
			            detectQuickTimeActiveXControl = True
			          End If
			        End If
			      End If
			    End Function
			
			
			]]>
			</vbscript>;;
		}
	}


	class BrowserError extends Error {
		public function BrowserError(message:String) {
			super(message);
			name="BrowserError";
		}
	}